#!/usr/bin/env python3
"""
专业领域资讯服务 - 一键安装脚本
适用于Windows、macOS、Linux系统
"""

import os
import sys
import subprocess
import platform
import json
from pathlib import Path
import sqlite3
import time

class Installer:
    def __init__(self):
        self.project_root = Path(__file__).parent
        self.backend_dir = self.project_root / "backend"
        self.frontend_dir = self.project_root / "frontend"
        self.data_dir = self.project_root / "data"
        
        # 创建必要的目录
        self.data_dir.mkdir(exist_ok=True)
        (self.project_root / "logs").mkdir(exist_ok=True)
        
        self.system = platform.system().lower()
        print(f"🖥️  检测到操作系统: {self.system}")
    
    def check_python_version(self):
        """检查Python版本"""
        version = sys.version_info
        if version.major < 3 or (version.major == 3 and version.minor < 8):
            print("❌ 需要Python 3.8或更高版本")
            print(f"当前版本: {version.major}.{version.minor}.{version.micro}")
            sys.exit(1)
        print(f"✅ Python版本检查通过: {version.major}.{version.minor}.{version.micro}")
    
    def install_backend_dependencies(self):
        """安装后端依赖"""
        print("\n📦 安装后端依赖...")
        
        requirements_file = self.backend_dir / "requirements.txt"
        if not requirements_file.exists():
            print("❌ 找不到requirements.txt文件")
            return False
        
        try:
            # 升级pip
            print("升级pip...")
            subprocess.run([sys.executable, "-m", "pip", "install", "--upgrade", "pip"], 
                         check=True, capture_output=True)
            
            # 逐个安装关键依赖
            print("安装核心依赖...")
            core_deps = [
                "fastapi==0.104.1",
                "uvicorn[standard]==0.24.0", 
                "pydantic==2.5.0",
                "pydantic-settings==2.1.0",
                "sqlalchemy==2.0.23",
                "requests==2.31.0",
                "feedparser==6.0.10",
                "python-dotenv==1.0.0"
            ]
            
            for dep in core_deps:
                try:
                    print(f"安装 {dep}...")
                    subprocess.run([sys.executable, "-m", "pip", "install", dep], 
                                 check=True, capture_output=True)
                except subprocess.CalledProcessError as e:
                    print(f"⚠️  安装 {dep} 失败，尝试安装最新版本...")
                    # 尝试安装最新版本
                    package_name = dep.split("==")[0]
                    subprocess.run([sys.executable, "-m", "pip", "install", package_name], 
                                 check=True, capture_output=True)
            
            # 安装其他依赖
            print("安装其他依赖...")
            other_deps = [
                "beautifulsoup4==4.12.2",
                "lxml==4.9.3", 
                "pyyaml==6.0.1",
                "python-dateutil==2.8.2",
                "pytz==2023.3",
                "aiofiles==23.2.1"
            ]
            
            for dep in other_deps:
                try:
                    subprocess.run([sys.executable, "-m", "pip", "install", dep], 
                                 check=True, capture_output=True)
                except subprocess.CalledProcessError:
                    print(f"⚠️  跳过 {dep}，使用系统默认版本")
            
            print("✅ 后端依赖安装完成")
            return True
            
        except subprocess.CalledProcessError as e:
            print(f"❌ 后端依赖安装失败: {e}")
            print("尝试使用备用方案...")
            return self.install_backend_dependencies_fallback()
    
    def install_backend_dependencies_fallback(self):
        """备用安装方案"""
        print("使用备用安装方案...")
        
        try:
            # 只安装最核心的依赖
            minimal_deps = [
                "fastapi",
                "uvicorn", 
                "pydantic",
                "requests",
                "feedparser"
            ]
            
            for dep in minimal_deps:
                try:
                    print(f"安装 {dep}...")
                    subprocess.run([sys.executable, "-m", "pip", "install", dep], 
                                 check=True, capture_output=True)
                except subprocess.CalledProcessError as e:
                    print(f"❌ 安装 {dep} 失败: {e}")
                    return False
            
            print("✅ 最小依赖安装完成")
            return True
            
        except Exception as e:
            print(f"❌ 备用安装也失败: {e}")
            return False
    
    def check_dependencies(self):
        """检查关键依赖是否可用"""
        print("\n🔍 检查依赖...")
        
        required_modules = [
            "fastapi",
            "uvicorn", 
            "pydantic",
            "requests",
            "feedparser",
            "sqlite3"  # 内置模块
        ]
        
        missing_modules = []
        
        for module in required_modules:
            try:
                __import__(module)
                print(f"✅ {module}")
            except ImportError:
                print(f"❌ {module} - 缺失")
                missing_modules.append(module)
        
        if missing_modules:
            print(f"\n⚠️  缺失模块: {', '.join(missing_modules)}")
            print("请手动安装缺失的依赖:")
            for module in missing_modules:
                print(f"pip install {module}")
            return False
        else:
            print("✅ 所有关键依赖检查通过")
            return True
    
    def install_frontend_dependencies(self):
        """安装前端依赖"""
        print("\n📦 安装前端依赖...")
        
        package_json = self.frontend_dir / "package.json"
        if not package_json.exists():
            print("❌ 找不到package.json文件")
            return False
        
        try:
            # 检查Node.js
            subprocess.run(["node", "--version"], check=True, capture_output=True)
            subprocess.run(["npm", "--version"], check=True, capture_output=True)
            
            # 安装依赖
            subprocess.run(["npm", "install"], cwd=self.frontend_dir, check=True, capture_output=True)
            
            print("✅ 前端依赖安装完成")
            return True
        except subprocess.CalledProcessError as e:
            print(f"❌ 前端依赖安装失败: {e}")
            print("请确保已安装Node.js和npm")
            return False
        except FileNotFoundError:
            print("❌ 找不到Node.js或npm，请先安装Node.js")
            return False
    
    def init_database(self):
        """初始化数据库"""
        print("\n🗄️  初始化数据库...")
        
        db_path = self.data_dir / "news.db"
        
        try:
            conn = sqlite3.connect(db_path)
            cursor = conn.cursor()
            
            # 创建文章表
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS articles (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    title TEXT NOT NULL,
                    content TEXT,
                    summary TEXT,
                    url TEXT,
                    source TEXT NOT NULL,
                    category TEXT,
                    keywords TEXT,
                    published_at TEXT,
                    created_at TEXT DEFAULT CURRENT_TIMESTAMP,
                    updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
                    embedding TEXT,
                    sentiment_score REAL,
                    relevance_score REAL,
                    is_read INTEGER DEFAULT 0,
                    is_bookmarked INTEGER DEFAULT 0
                )
            ''')
            
            # 创建关键词表
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS keywords (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    keyword TEXT UNIQUE NOT NULL,
                    category TEXT,
                    description TEXT,
                    priority INTEGER DEFAULT 1,
                    is_active INTEGER DEFAULT 1,
                    created_at TEXT DEFAULT CURRENT_TIMESTAMP,
                    updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
                    match_count INTEGER DEFAULT 0,
                    last_match_at TEXT
                )
            ''')
            
            # 插入一些默认关键词
            default_keywords = [
                ("人工智能", "ai", "AI相关技术", 1),
                ("机器学习", "ai", "机器学习技术", 1),
                ("深度学习", "ai", "深度学习技术", 1),
                ("自然语言处理", "ai", "NLP技术", 1),
                ("计算机视觉", "ai", "CV技术", 1),
                ("区块链", "tech", "区块链技术", 1),
                ("云计算", "tech", "云计算技术", 1),
                ("大数据", "tech", "大数据技术", 1),
                ("量子计算", "science", "量子计算技术", 1),
                ("生物技术", "science", "生物技术", 1)
            ]
            
            for keyword, category, description, priority in default_keywords:
                cursor.execute('''
                    INSERT OR IGNORE INTO keywords (keyword, category, description, priority)
                    VALUES (?, ?, ?, ?)
                ''', (keyword, category, description, priority))
            
            conn.commit()
            conn.close()
            
            print("✅ 数据库初始化完成")
            return True
        except Exception as e:
            print(f"❌ 数据库初始化失败: {e}")
            return False
    
    def create_config_files(self):
        """创建配置文件"""
        print("\n⚙️  创建配置文件...")
        
        # 创建.env文件
        env_content = """# 应用配置
APP_NAME=专业领域资讯服务
DEBUG=true

# 数据库配置
DATABASE_URL=sqlite:///./data/news.db

# API密钥配置（可选）
OPENAI_API_KEY=
NEWS_API_KEY=
PUBMED_API_KEY=

# 数据源配置
RSS_UPDATE_INTERVAL=3600
API_UPDATE_INTERVAL=1800

# 文件存储
DATA_DIR=./data
UPLOAD_DIR=./data/uploads

# 日志配置
LOG_LEVEL=INFO
LOG_FILE=./logs/app.log
"""
        
        env_file = self.project_root / ".env"
        with open(env_file, 'w', encoding='utf-8') as f:
            f.write(env_content)
        
        # 创建启动脚本
        if self.system == "windows":
            self.create_windows_scripts()
        else:
            self.create_unix_scripts()
        
        print("✅ 配置文件创建完成")
        return True
    
    def create_windows_scripts(self):
        """创建Windows启动脚本"""
        # 启动后端脚本
        backend_script = """@echo off
cd /d "%~dp0"
cd backend
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
pause
"""
        
        with open(self.project_root / "start_backend.bat", 'w', encoding='utf-8') as f:
            f.write(backend_script)
        
        # 启动前端脚本
        frontend_script = """@echo off
cd /d "%~dp0"
cd frontend
npm start
pause
"""
        
        with open(self.project_root / "start_frontend.bat", 'w', encoding='utf-8') as f:
            f.write(frontend_script)
        
        # 一键启动脚本
        start_all_script = """@echo off
echo 启动专业领域资讯服务...
echo.
echo 正在启动后端服务...
start "后端服务" cmd /k "cd /d "%~dp0" && cd backend && python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload"
timeout /t 3 /nobreak >nul
echo 正在启动前端服务...
start "前端服务" cmd /k "cd /d "%~dp0" && cd frontend && npm start"
echo.
echo 服务启动完成！
echo 后端地址: http://localhost:8000
echo 前端地址: http://localhost:3000
echo.
echo 按任意键退出...
pause >nul
"""
        
        with open(self.project_root / "start_all.bat", 'w', encoding='utf-8') as f:
            f.write(start_all_script)
    
    def create_unix_scripts(self):
        """创建Unix系统启动脚本"""
        # 启动后端脚本
        backend_script = """#!/bin/bash
cd "$(dirname "$0")"
cd backend
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
"""
        
        backend_script_path = self.project_root / "start_backend.sh"
        with open(backend_script_path, 'w', encoding='utf-8') as f:
            f.write(backend_script)
        os.chmod(backend_script_path, 0o755)
        
        # 启动前端脚本
        frontend_script = """#!/bin/bash
cd "$(dirname "$0")"
cd frontend
npm start
"""
        
        frontend_script_path = self.project_root / "start_frontend.sh"
        with open(frontend_script_path, 'w', encoding='utf-8') as f:
            f.write(frontend_script)
        os.chmod(frontend_script_path, 0o755)
        
        # 一键启动脚本
        start_all_script = """#!/bin/bash
echo "启动专业领域资讯服务..."
echo ""
echo "正在启动后端服务..."
cd "$(dirname "$0")"
cd backend
python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload &
sleep 3
echo "正在启动前端服务..."
cd ../frontend
npm start &
echo ""
echo "服务启动完成！"
echo "后端地址: http://localhost:8000"
echo "前端地址: http://localhost:3000"
echo ""
echo "按 Ctrl+C 停止服务"
wait
"""
        
        start_all_script_path = self.project_root / "start_all.sh"
        with open(start_all_script_path, 'w', encoding='utf-8') as f:
            f.write(start_all_script)
        os.chmod(start_all_script_path, 0o755)
    
    def test_installation(self):
        """测试安装"""
        print("\n🧪 测试安装...")
        
        try:
            # 测试后端
            print("测试后端服务...")
            result = subprocess.run([sys.executable, "-c", "import fastapi; print('FastAPI导入成功')"], 
                                  capture_output=True, text=True)
            if result.returncode == 0:
                print("✅ 后端测试通过")
            else:
                print("❌ 后端测试失败")
                return False
            
            # 测试前端
            print("测试前端依赖...")
            result = subprocess.run(["npm", "list", "--depth=0"], cwd=self.frontend_dir, 
                                  capture_output=True, text=True)
            if result.returncode == 0:
                print("✅ 前端测试通过")
            else:
                print("❌ 前端测试失败")
                return False
            
            print("✅ 所有测试通过")
            return True
        except Exception as e:
            print(f"❌ 测试失败: {e}")
            return False
    
    def show_usage(self):
        """显示使用说明"""
        print("\n" + "="*60)
        print("🎉 安装完成！")
        print("="*60)
        print("\n📖 使用说明:")
        print("1. 启动服务:")
        if self.system == "windows":
            print("   - 双击 'start_all.bat' 一键启动")
            print("   - 或分别运行 'start_backend.bat' 和 'start_frontend.bat'")
        else:
            print("   - 运行 './start_all.sh' 一键启动")
            print("   - 或分别运行 './start_backend.sh' 和 './start_frontend.sh'")
        
        print("\n2. 访问地址:")
        print("   - 前端界面: http://localhost:3000")
        print("   - 后端API: http://localhost:8000")
        print("   - API文档: http://localhost:8000/docs")
        
        print("\n3. 功能说明:")
        print("   - 添加关键词: 在界面中添加你关注的专业关键词")
        print("   - 数据收集: 系统会自动从RSS源收集相关文章")
        print("   - 文章浏览: 查看匹配关键词的最新文章")
        print("   - 本地文件: 支持导入本地.txt、.md、.json文件")
        
        print("\n4. 数据存储:")
        print(f"   - 数据库文件: {self.data_dir / 'news.db'}")
        print(f"   - 日志文件: {self.project_root / 'logs'}")
        
        print("\n5. 停止服务:")
        print("   - 在终端中按 Ctrl+C")
        print("   - 或关闭对应的终端窗口")
        
        print("\n" + "="*60)
        print("🚀 开始使用你的专业领域资讯服务吧！")
        print("="*60)
    
    def run(self):
        """运行安装程序"""
        print("🚀 专业领域资讯服务 - 一键安装程序")
        print("="*50)
        
        # 检查Python版本
        self.check_python_version()
        
        # 检查关键依赖
        if not self.check_dependencies():
            print("❌ 安装失败，请检查错误信息")
            return False

        # 安装后端依赖
        if not self.install_backend_dependencies():
            print("❌ 安装失败，请检查错误信息")
            return False
        
        # 安装前端依赖
        if not self.install_frontend_dependencies():
            print("❌ 安装失败，请检查错误信息")
            return False
        
        # 初始化数据库
        if not self.init_database():
            print("❌ 安装失败，请检查错误信息")
            return False
        
        # 创建配置文件
        if not self.create_config_files():
            print("❌ 安装失败，请检查错误信息")
            return False
        
        # 测试安装
        if not self.test_installation():
            print("❌ 安装失败，请检查错误信息")
            return False
        
        # 显示使用说明
        self.show_usage()
        
        return True

if __name__ == "__main__":
    installer = Installer()
    success = installer.run()
    
    if success:
        print("\n✅ 安装成功完成！")
        sys.exit(0)
    else:
        print("\n❌ 安装失败，请检查错误信息")
        sys.exit(1) 